#include "GMailManager.h"
#include "Character/Player.h"
#include "Character/PlayerMgr.h"
#include "LogicService.h"
#include "Common/Item/ItemMgr.h"
#include "Common/TableData/ItemItemCfg.h"

using namespace ProtoBuf;

GMailManager::GMailManager()
{
	_sysConfigMail.clear();
}

GMailManager::~GMailManager()
{
	_sysConfigMail.clear();
}

bool GMailManager::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetLogicService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return false;
	}
	pMessageDispatch->registerClientHandler(EMODULE_ID_MAIL, this);
	pMessageDispatch->registerServerHandler(EMODULE_ID_MAIL, this);
	pMessageDispatch->registerDBProxyHandler(EMODULE_ID_MAIL, this);

	g_GetEvent()->Subscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_LOGIN_GAME, 0, CREATURE_PLAYER, NULL);

	//开始加载系统邮件表
	g_GetTimerAxis()->SetTimer(TIMER_ID_StartLoad_SysMailData, 2 * 1000, this);

	return true;
}

void GMailManager::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetLogicService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return;
	}
	pMessageDispatch->unregisterClientHandler(EMODULE_ID_MAIL);
	pMessageDispatch->unregisterServerHandler(EMODULE_ID_MAIL);
	pMessageDispatch->unregisterDBProxyHandler(EMODULE_ID_MAIL);

	g_GetTimerAxis()->KillAllTimer(this);

	g_GetEvent()->UnSubscribeAll(this);
}

void GMailManager::onClientMessage(uint32_t actionId, RECV_PACKAGE& package, uint64_t Id /* = 0 */)
{
	Player* pPlayer = nullptr;
	pPlayer = (Player*)(package.session->GetUserData().ptr);
	if (nullptr == pPlayer)
	{
		return;
	}
	
}

void GMailManager::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case CENTER_SERVER_PROTOCOL_SEND_MAIL_TO_LOGIC:
	{
		OnSendMailReq(package);
	}
	break;
	//case CENTER_SERVER_PROTOCOL_SEND_MAIL_ERROR_NOTIFY:
	//{
	//	OnSendMailError(package);
	//}
	//	break;
	case CENTER_SERVER_PROTOCOL_GET_MAIL_ATTACHMENT_TO_LOGIC:
	{
		OnGetMailAttachment(package);
	}
	break;
	case CENTER_SERVER_PROTOCOL_GET_ALL_MAIL_ATTACHMENT_TO_LOGIC:
	{
		OnGetAllMailAttachment(package);
	}
	break;
	default:
		break;
	}
}

void GMailManager::onDBProxyMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case DBPROXY_PROTOCOL_SYSMAIL_DATA_RSP: //系统邮件返回
	{
		SysMailInfoLoadRsp rsp;
		if (!rsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
		{
			MMOLOG_FMT_ERROR("[center] SysMailInfoLoadRsp return but parse failed");
			return;
		}
		LoadSysMailDBRet(rsp);
	}
	break;
	default:
		break;
	}
}

void GMailManager::LoadSysMailDBRet(SysMailInfoLoadRsp& rsp)
{
	for (int32_t i = 0; i < rsp.maillist_size(); i++)
	{
		const SysMailInfo& sysMailInfo = rsp.maillist(i);
		_sysConfigMail[sysMailInfo.mailid()] = sysMailInfo;
	}
}

void GMailManager::OnTimer(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case TIMER_ID_StartLoad_SysMailData:
	{
		if (g_GetLogicService()->IsConnectDBProxy())
		{
			SysMailInfoLoadReq req;
			if (!g_GetLogicService()->SendDataToDBProxy(EMODULE_ID_MAIL, DBPROXY_PROTOCOL_SYSMAIL_DATA_REQ, &req))
			{
				LogDebugFmtPrint("[logic] SysMailInfoLoadReq SendDataToDBProxy failed");
			}
			else
			{
				LogDebugFmtPrint("[logic] start load sys mail data....");
			}

			g_GetTimerAxis()->KillTimer(TIMER_ID_StartLoad_SysMailData, this);
		}
		break;
	}
	default:
		break;
	}
}

void GMailManager::OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen)
{
	switch (nEventID)
	{
	case EVENT_LOGIN_GAME: //登陆
	{
		LoginGame loginGame = *(LoginGame*)pContext;
		OnLoginGame(loginGame);
		break;
	}
	default:
		break;
	}
}

void GMailManager::OnLoginGame(LoginGame& loginGame)
{
	CharIDType charId = loginGame.cid;
	Player* pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("[logic] GMailManager::OnLoginGame but Player is nullptr charId:%lu", charId);
		return;
	}

	VEC_STRING& vecBuChan = pPlayer->GetChangeVersion();
	uint32_t nowTime = Time::Now().sec();
	for (SysConfigMailMap::iterator iter = _sysConfigMail.begin(); iter != _sysConfigMail.end(); ++iter)
	{
		//判断是否是过期了
		if (nowTime > iter->second.endtime())
		{
			continue;
		}

		//如果没有过期 判断是否已经领取过了
		VEC_STRING::iterator it = find(vecBuChan.begin(), vecBuChan.end(), iter->second.mailid());
		if (it == vecBuChan.end())
		{
			std::vector<ItemProtoInfo> itemList;
			for (int32_t i = 0; i < iter->second.attachment().iteminfo_size(); i++)
			{
				itemList.push_back(iter->second.attachment().iteminfo(i));
			}

			//发送补偿邮件
			SendSystemMail(pPlayer->GetCid(), iter->second.topic(), iter->second.content(), iter->second.gold(), iter->second.bindgold(), iter->second.diamond(), iter->second.binddiamond(), 0, itemList);

			//记录领取过的补偿邮件
			vecBuChan.push_back(iter->second.mailid());
		}
	}

	//删除过期无效的补偿邮件信息
	VEC_STRING::iterator vIter = vecBuChan.begin();
	while (vIter != vecBuChan.end())
	{
		SysConfigMailMap::iterator mIter = _sysConfigMail.find(*vIter);
		if (mIter == _sysConfigMail.end())
		{
			vIter = vecBuChan.erase(vIter);
		}
		else 
		{
			++vIter;
		}
	}
}

bool GMailManager::OnSendMailReq(RECV_PACKAGE &package)
{
	WGSendMailReq sendMailReq;
	WCSendMailRsp sendMailRsp;

	if (!sendMailReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[logic] GMailManager::OnSendMailReq GWSendMailReq parse failed...");
		return false;
	}

	CharIDType charId = sendMailReq.charid();
	Player* pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("[logic] GMailManager::OnSendMailReq but Player is nullptr charId:%u", charId);
		return false;
	}
	if (ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState()) //如果是切换逻辑节点，这个时候玩家数据已经带到中心服去了，这里直接领取失败
	{
		LogErrFmtPrint("[logic] OnSendMailReq...ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState()....cid:%lu,zid:%d,id:%d ", charId, g_GetLogicService()->GetZID(), g_GetLogicService()->GetID());

		//如果是跨逻辑服切场景，直接返回发送失败
		sendMailRsp.set_ret(RET_FAIL);
		pPlayer->SendDataToClient(EMODULE_ID_MAIL, SERVER_TO_CLIENT_SENDMAIL, &sendMailRsp);
		return false;
	}
	ERetCode ret = SendNormalMail(pPlayer, *(sendMailReq.mutable_req()));
	if (ret != RET_SUCCESS)
	{
		sendMailRsp.set_ret(ret);
		pPlayer->SendDataToClient(EMODULE_ID_MAIL, SERVER_TO_CLIENT_SENDMAIL, &sendMailRsp);
	}

	return true;
}

bool GMailManager::OnGetMailAttachment(RECV_PACKAGE &package)
{
	WGGetMailAttachmentReq getMailAttachmentReq;
	GCGetMailAttachmentRsp getMailAttachmentRsp;

	if (!getMailAttachmentReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("GMailManager::OnGetMailAttachment WGGetMailAttachmentReq parse failed...");
		return false;
	}

	CharIDType charId = getMailAttachmentReq.charid();
	MailIDType mailId = getMailAttachmentReq.mailid();
	uint32_t source = getMailAttachmentReq.source();
	int32_t ret = RET_FAIL;
	Player* pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr != pPlayer)
	{
		if (ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState()) //如果是切换逻辑节点，这个时候玩家数据已经带到中心服去了，这里直接领取失败
		{
			LogErrFmtPrint("[logic] OnGetMailAttachment11...ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState()....cid:%lu,zid:%d,id:%d ", charId, g_GetLogicService()->GetZID(), g_GetLogicService()->GetID());
		}
		else
		{
			Part *pPackage = pPlayer->GetPart(PART_PACKAGE);
			if (nullptr != pPackage)
			{
				ret = RET_SUCCESS;
				//领取交易邮件需要扣除费用
				uint32_t mailType = getMailAttachmentReq.mailtype();
				if (mailType == MAIL_TYPE_TRADE)
				{
					uint32_t sellType = getMailAttachmentReq.selltype();
					int32_t sellNum = getMailAttachmentReq.sellnum();
					if (sellType != MAIL_TRADING_SELL_TYPE_DIAMOND)
					{
						int64_t nHasGold = pPlayer->GetAttr(C_GOLD);
						if (nHasGold < (int64_t)sellNum)
						{
							ret = RET_GOLD_LACK;
						}
					}
					else  //钻石
					{
						uint32_t nHasDiamond = pPlayer->GetAttr(C_DIAMOND);
						if (nHasDiamond < (uint32_t)sellNum)
						{
							//钻石不足 RET_GOLD_LACK
							ret = RET_DIAMOND_LACK;
						}
					}
				}
				if (RET_SUCCESS == ret)
				{
					//添加附件到背包中去
					VEC_ITEM_PROTO vecProtoItem;
					vecProtoItem.clear();
					MailAttachmentList* mailAttachMentList = getMailAttachmentReq.mutable_attachment();
					for (int i = 0; i < mailAttachMentList->iteminfo_size(); i++)
					{
						vecProtoItem.push_back(mailAttachMentList->mutable_iteminfo(i));
					}
					SItemSourceParam sourceParam;
					sourceParam.source = S_TradeMail;	
					if (MAIL_SOURCE_UNION_ESCOTT == source)
					{
						sourceParam.notifySource = ENotifyType_Item_UnionEscort;
					}
					if (pPackage->AddItem(vecProtoItem, sourceParam))
					{
						uint32_t sellType = getMailAttachmentReq.selltype();
						int32_t sellNum = getMailAttachmentReq.sellnum();
						int32_t gold = getMailAttachmentReq.gold();
						int32_t diamond = getMailAttachmentReq.diamond();
						int32_t bindDiamond = getMailAttachmentReq.binddiamond();
						uint32_t arenaScore = getMailAttachmentReq.arenascore();
						if (mailType == MAIL_TYPE_TRADE) //如果是交易邮件那么提取附件要扣除费用
						{
							//扣除货币
							if (sellType != MAIL_TRADING_SELL_TYPE_DIAMOND)
							{
								//pPlayer->AddAttr(C_GOLD, -1 * (int64_t)sellNum, true);
								pPlayer->AddSourceAttr(C_GOLD, -1 * (int64_t)sellNum, true, S_TradeMail);
							}
							else  //钻石
							{
								//pPlayer->AddAttr(C_DIAMOND, -sellNum, true);
								pPlayer->AddSourceAttr(C_DIAMOND, -sellNum, true, S_TradeMail);
							}
						}
						else if (mailType == MAIL_TYPE_PAY) //如果是提取已经付费的交易邮件那么是增加费用
						{
							//扣除货币
							if (sellType != MAIL_TRADING_SELL_TYPE_DIAMOND)
							{
								//pPlayer->AddAttr(C_GOLD, sellNum, true);
								pPlayer->AddSourceAttr(C_GOLD, sellNum, true, S_TradeMail);
							}
							else  //钻石
							{
								//pPlayer->AddAttr(C_DIAMOND, sellNum, true);
								pPlayer->AddSourceAttr(C_DIAMOND, sellNum, true, S_TradeMail);
							}
						}

						//pPlayer->AddAttr(C_GOLD, gold, true);
						pPlayer->AddSourceAttr(C_GOLD, gold, true, S_TradeMail);
						//pPlayer->AddAttr(C_DIAMOND, diamond, true);
						pPlayer->AddSourceAttr(C_DIAMOND, diamond, true, S_TradeMail);
						//pPlayer->AddAttr(C_DIAMOND_BIND, bindDiamond, true);
						pPlayer->AddSourceAttr(C_DIAMOND_BIND, bindDiamond, true, S_TradeMail);
						//pPlayer->AddAttr(C_ARENA_SCORE, arenaScore, true);
						pPlayer->AddSourceAttr(C_ARENA_SCORE, arenaScore, true, S_ARENA);
					}
					else
					{
						ret = RET_PACKAGE_SPACE_NOT_ENOUGH;
					}
				}

			}
			else
			{
				MMOLOG_FMT_DEBUG("[logic] GMailManager::OnGetMailAttachment pPackage part is nullptr charId=%u", pPlayer->GetId());
			}
		}
	}
	else
	{
		MMOLOG_FMT_ERROR("GMailManager::OnGetMailAttachment but pPlayer is nullptr, cid:%lu ", charId);
	}

	
	if (nullptr != pPlayer)
	{
		//通知客户端
		getMailAttachmentRsp.set_ret(ret);
		getMailAttachmentRsp.set_mailid(mailId);
		pPlayer->SendDataToClient(EMODULE_ID_MAIL, SERVER_TO_CLIENT_GETMAILATTACHMENT, &getMailAttachmentRsp);
	}
	//通知世界服获取失败 解除附件的绑定
	GWUpdateMailNotify notifyMsg;
	notifyMsg.set_charid(charId);
	notifyMsg.add_idlist(mailId);
	notifyMsg.set_ret(ret);
	g_GetLogicService()->SendDataToCenter(EMODULE_ID_MAIL,CENTER_SERVER_PROTOCOL_UPDATE_MAIL_NOTIFY, &notifyMsg);

	return true;
}

bool GMailManager::OnGetAllMailAttachment(RECV_PACKAGE &package)
{
	WGGetAllMailAttachmentReq getMailAttachmentReq;
	GCGetAllMailAttachmentRsp getAllMailAttachmentRsp;

	if (!getMailAttachmentReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("GMailManager::OnGetAllMailAttachment WGGetAllMailAttachmentReq parse failed...");
		return false;
	}

	int32_t ret = RET_FAIL;
	CharIDType charId = getMailAttachmentReq.charid();
	Player* pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr != pPlayer)
	{
		if (ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState()) //如果是切换逻辑节点，这个时候玩家数据已经带到中心服去了，这里直接领取失败
		{
			LogErrFmtPrint("[logic] OnGetMailAttachment11...ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState()....cid:%lu,zid:%d,id:%d ", charId, g_GetLogicService()->GetZID(), g_GetLogicService()->GetID());
		}
		else
		{
			Part *pPackage = pPlayer->GetPart(PART_PACKAGE);
			if (nullptr != pPackage)
			{
				int32_t gold = 0;
				int32_t diamond = 0;
				int32_t bindDiamond = 0;
				int32_t arenaScore = 0;
				int32_t tradeGold = 0;
				VEC_ITEM_PROTO_EX vecProtoItem;
				vecProtoItem.clear();
				VEC_ITEM_PROTO_EX vecProtoItemEx;
				vecProtoItemEx.clear();
				VEC_ITEM_PROTO_EX vecProtoItemEscort;//工会镖车有奖奖励
				vecProtoItemEscort.clear();
				for (int i = 0; i < getMailAttachmentReq.attachmentdatalist_size(); i++)
				{
					OneMailAttachmentData* pAttachmentData = getMailAttachmentReq.mutable_attachmentdatalist(i);
					MailIDType mailId = pAttachmentData->mailid();
					MailAttachmentList* mailAttachMentList = pAttachmentData->mutable_attachment();
					for (int i = 0; i < mailAttachMentList->iteminfo_size(); i++)
					{
						const ItemProtoInfo &proto = mailAttachMentList->iteminfo(i);
						vecProtoItem.push_back(proto);
						if (MAIL_SOURCE_UNION_ESCOTT == pAttachmentData->source())
						{
							vecProtoItemEscort.push_back(proto);
						}
						else
						{
							vecProtoItemEx.push_back(proto);
						}						
					}
					gold += pAttachmentData->gold();
					diamond += pAttachmentData->diamond();
					bindDiamond += pAttachmentData->binddiamond();
					arenaScore += pAttachmentData->arenascore();
					if (pAttachmentData->source() == MAIL_SOURCE_AUCTIONEER)
					{
						tradeGold += pAttachmentData->gold();
					}
					getAllMailAttachmentRsp.add_idlist(mailId);
				}
				ret = RET_SUCCESS;
				if (vecProtoItem.size() > 0)
				{
					if (!pPackage->CanAddItem(vecProtoItem))
					{
						ret = RET_PACKAGE_SPACE_NOT_ENOUGH;
					}
					else
					{
						//添加附件到背包中去
						SItemSourceParam sourceParam;
						sourceParam.source = S_TradeMail;
						pPackage->AddItem(vecProtoItemEx, sourceParam);
						//镖车邮件附件
						sourceParam.notifySource = ENotifyType_Item_UnionEscort;
						pPackage->AddItem(vecProtoItemEscort, sourceParam);
					}
				}
				if (RET_SUCCESS == ret)
				{
					if (gold > 0)
					{
						//pPlayer->AddAttr(C_GOLD, gold, true);
						pPlayer->AddSourceAttr(C_GOLD, gold, true, S_TradeMail);
					}
					if (diamond > 0)
					{
						//pPlayer->AddAttr(C_DIAMOND, diamond, true);
						pPlayer->AddSourceAttr(C_DIAMOND, diamond, true, S_TradeMail);
					}
					if (bindDiamond > 0)
					{
						//pPlayer->AddAttr(C_DIAMOND_BIND, bindDiamond, true);
						pPlayer->AddSourceAttr(C_DIAMOND_BIND, bindDiamond, true, S_TradeMail);
					}
					if (arenaScore > 0)
					{
						//pPlayer->AddAttr(C_ARENA_SCORE, arenaScore, true);
						pPlayer->AddSourceAttr(C_ARENA_SCORE, arenaScore, true, S_ARENA);
					}
				}

			}
			else
			{
				MMOLOG_FMT_DEBUG("[logic] GMailManager::OnGetAllMailAttachment pPackage part is nullptr charId=%u", pPlayer->GetId());
			}
		}		
	}
	else
	{
		MMOLOG_FMT_ERROR("GMailManager::OnGetAllMailAttachment but pPlayer is nullptr, cid:%lu ",charId);
	}
	if (nullptr != pPlayer)
	{
		getAllMailAttachmentRsp.set_ret(ret);
		pPlayer->SendDataToClient(EMODULE_ID_MAIL, SERVER_TO_CLIENT_GETALLMAILATTACHMENT, &getAllMailAttachmentRsp);
	}

	//通知世界服邮件删除附件数据
	GWUpdateMailNotify notifyMsg;
	notifyMsg.set_charid(charId);
	notifyMsg.mutable_idlist()->CopyFrom(getAllMailAttachmentRsp.idlist());
	notifyMsg.set_ret(ret);
	g_GetLogicService()->SendDataToCenter(EMODULE_ID_MAIL, CENTER_SERVER_PROTOCOL_UPDATE_MAIL_NOTIFY, &notifyMsg);

	return true;
}

ERetCode GMailManager::SendNormalMail(Player* pPlayer, CWSendMailReq& sendMailReq)
{
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("[logic] GMailManager::SendNormalMail but send player is nullptr");
		return RET_FAIL;
	}

	//check level
	if (pPlayer->GetAttr(C_LEVEL) < MAIL_SEND_LEVEL_LIMIT)
	{
		return RET_MAIL_SEND_LEVEL_LIMIT;
	}

	Part *pPackage = pPlayer->GetPart(PART_PACKAGE);
	if (nullptr == pPackage)
	{
		MMOLOG_FMT_DEBUG("[logic] GMailManager::SendNormalMail pPackage part is nullptr charId=%u", pPlayer->GetId());
		return RET_FAIL;
	}

	uint32_t mailType = sendMailReq.mailtype();
	if (mailType != MAIL_TYPE_NORMAL && mailType != MAIL_TYPE_TRADE)
	{
		return RET_MAIL_SEND_TYPE_ERROR;
	}

	GWSendMailReq gwSendMailReq;
	gwSendMailReq.set_mailtype(sendMailReq.mailtype());
	gwSendMailReq.set_sendid(pPlayer->GetId());
	gwSendMailReq.set_targetname(sendMailReq.targetname());
	gwSendMailReq.set_targetid(sendMailReq.targetid());
	gwSendMailReq.set_title(sendMailReq.title());
	gwSendMailReq.set_content(sendMailReq.content());
	gwSendMailReq.set_selltype(sendMailReq.selltype());
	gwSendMailReq.set_sellnum(sendMailReq.sellnum());

	//只有交易邮件才会带有附件 并且只有一个附件 并且需要检查费用是否够了
	if (mailType == MAIL_TYPE_TRADE && sendMailReq.mailattachment_size() > 0)
	{
		if (sendMailReq.mailattachment_size() > MAX_TRADE_MAIL_ATTATCH_NUM)
		{
			return RET_MAIL_TRADING_ATTCHMENT_LIMIT;
		}

		//检查货币类型是否正确
		uint32_t sellType = sendMailReq.selltype();
		if (sellType <= MAIL_TRADING_SELL_TYPE_NONE || sellType > MAIL_TRADING_SELL_TYPE_DIAMOND)
		{
			return RET_MAIL_TRADING_SELL_TYPE_ERROR;
		}


		//判断该位置是否有物品
		MAP_UINT16_INT32 mapIndexItem;
		for (int32_t i = 0; i < sendMailReq.mailattachment_size(); i++)
		{
			const MailAttachment& mailAttachMent = sendMailReq.mailattachment(i);
			uint32_t nGridIndex = mailAttachMent.gridindex();
			int32_t nNum = mailAttachMent.num();

			//客户端有可能上报了一个格子的上来
			MAP_UINT16_INT32::iterator iter = mapIndexItem.find(nGridIndex);
			if (iter == mapIndexItem.end())
			{
				mapIndexItem[nGridIndex] = nNum;
			}
			else
			{
				mapIndexItem[nGridIndex] += nNum;
			}
		}

		for (MAP_UINT16_INT32::iterator iter = mapIndexItem.begin(); iter != mapIndexItem.end(); ++iter)
		{
			CItemBase* pItemBase = const_cast<CItemBase*>(pPackage->GetItem(iter->first));
			if (nullptr == pItemBase)
			{
				return RET_MAIL_GRID_INDEX_ERROR;
			}

			if ((int32_t)pItemBase->GetNum() < iter->second || iter->second < 0)
			{
				return RET_MAIL_GOODS_NUM_LIMIT;
			}

			if (!g_GetItemMgr()->CanTrade(pItemBase->GetItemID(), pItemBase->GetBind()))
			{
				return RET_MAIL_GOODS_CAN_NOT_TRADE;
			}
		}

		for (int32_t i = 0; i < sendMailReq.mailattachment_size(); i++)
		{
			const MailAttachment& mailAttachMent = sendMailReq.mailattachment(i);
			uint32_t nGridIndex = mailAttachMent.gridindex();
			int32_t nNum = mailAttachMent.num();

			CItemBase* pItemBase = const_cast<CItemBase*>(pPackage->GetItem(nGridIndex));
			if (nullptr == pItemBase)
			{
				return RET_MAIL_GRID_INDEX_ERROR;
			}

			//设置邮件附件信息
			MailAttachmentList* pMailAttachmentList = gwSendMailReq.mutable_attachment();
			g_GetItemMgr()->SetItemProtoInfo(pItemBase, pMailAttachmentList->add_iteminfo(), nNum);
		}

		//移除物品
		SItemSourceParam sourceParam;
		pPackage->RemoveItem(mapIndexItem, sourceParam);
	}
	else
	{
		//清除防作弊数据
		sendMailReq.set_selltype(MAIL_TRADING_SELL_TYPE_NONE);
		sendMailReq.set_sellnum(0);
		sendMailReq.clear_mailattachment();
	}

	//发往世界服
	g_GetLogicService()->SendDataToCenter(EMODULE_ID_MAIL, CENTER_SERVER_PROTOCOL_SEND_MAIL_REQ, &gwSendMailReq);

	return RET_SUCCESS;
}

bool GMailManager::SendSystemMail(CharIDType destId, string topic, string content, uint32_t gold, uint32_t bindGold, uint32_t diamond, uint32_t bindDiamond, uint32_t arenaScore, VEC_ITEM_PROTO_EX& itemList)
{
	if (topic.length() <= 0)
	{
		LogErrFmtPrint("[logic] SendSystemMail11...topic.length() <= 0 || topic.length() > MAX_MAIL_TOPIC_LEN..destid:%lu,gold:%u,bindGold:%u, diamond:%u, bindDiamond:%u ,arenaScore:%u, topic:%s,content:%s ", destId, gold, bindGold, diamond, bindDiamond, arenaScore, topic.c_str(), content.c_str());
		return false;
	}

	if (itemList.size() > MAX_MAIL_ATTATCH_NUM)
	{
		LogErrFmtPrint("[logic] SendSystemMail11...itemList.size() > MAX_MAIL_ATTATCH_NUM... destid:%lu,gold:%u,bindGold:%u, diamond:%u, bindDiamond:%u ,arenaScore:%u,attatchsize:%d, topic:%s,content:%s ", destId, gold, bindGold, diamond, bindDiamond, arenaScore, (int32_t)itemList.size(), topic.c_str(), content.c_str());
		return false;
	}

	if (content.length() > MAX_MAIL_CONTENT_LEN)
	{
		LogWarningFmtPrint("[logic] SendSystemMail11...content.length() > MAX_MAIL_CONTENT_LEN..destid:%lu,gold:%u,bindGold:%u, diamond:%u, bindDiamond:%u ,arenaScore:%u, topic:%s,content:%s ", destId, gold, bindGold, diamond, bindDiamond, arenaScore, topic.c_str(), content.c_str());
	}

	

	GWSendSystemMailReq reqMsg;
	reqMsg.set_destid(destId);
	reqMsg.set_title(topic.length() <= MAX_MAIL_TOPIC_LEN ? topic : topic.substr(0, MAX_MAIL_TOPIC_LEN));
	reqMsg.set_content(content.length() <= MAX_MAIL_CONTENT_LEN ? content : content.substr(0, MAX_MAIL_CONTENT_LEN));
	reqMsg.set_gold(gold);
	reqMsg.set_bindgold(bindGold);
	reqMsg.set_diamond(diamond);
	reqMsg.set_binddiamond(bindDiamond);
	reqMsg.set_arenascore(arenaScore);
	
	MailAttachmentList* pMailAttachmentList = reqMsg.mutable_attachment();
	for (uint32_t i = 0; i < itemList.size(); i++)
	{
		pMailAttachmentList->add_iteminfo()->CopyFrom(itemList[i]);
	}

	if (!g_GetLogicService()->SendDataToCenter(EMODULE_ID_MAIL, CENTER_SERVER_PROTOCOL_SEND_SYSTEM_MAIL, &reqMsg))
	{
		LogErrFmtPrint("[logic] SendSystemMail11...SendDataToCenter failed...destid:%lu,gold:%u,bindGold:%u, diamond:%u, bindDiamond:%u ,arenaScore:%u, topic:%s,content:%s ", destId, gold, bindGold, diamond, bindDiamond, arenaScore, topic.c_str(), content.c_str());
		return false;
	}
	return true;
}


bool GMailManager::SendSystemMail(CharIDType destId, string topic, string content, uint32_t gold, uint32_t bindGold, uint32_t diamond, uint32_t bindDiamond, uint32_t arenaScore, LIST_ITEM &lstItem)
{
	if (topic.length() <= 0)
	{
		LogErrFmtPrint("[logic] SendSystemMail...topic.length() <= 0 || topic.length() > MAX_MAIL_TOPIC_LEN..destid:%lu,gold:%u,bindGold:%u, diamond:%u, bindDiamond:%u ,arenaScore:%u, topic:%s,content:%s ", destId, gold, bindGold, diamond, bindDiamond, arenaScore, topic.c_str(), content.c_str());
		return false;
	}
	if (lstItem.size() > MAX_MAIL_ATTATCH_NUM)
	{
		LogErrFmtPrint("[logic] SendSystemMail...lstItem.size() > MAX_MAIL_ATTATCH_NUM... destid:%lu,gold:%u,bindGold:%u, diamond:%u, bindDiamond:%u ,arenaScore:%u,attatchsize:%d, topic:%s,content:%s ", destId, gold, bindGold, diamond, bindDiamond, arenaScore, (int32_t)lstItem.size(), topic.c_str(), content.c_str());
		return false;
	}

	if (content.length() > MAX_MAIL_CONTENT_LEN)
	{
		LogWarningFmtPrint("[logic] SendSystemMail...content.length() > MAX_MAIL_CONTENT_LEN..destid:%lu,gold:%u,bindGold:%u, diamond:%u, bindDiamond:%u ,arenaScore:%u, topic:%s,content:%s ", destId, gold, bindGold, diamond, bindDiamond, arenaScore, topic.c_str(), content.c_str());
	}
	string strTopic = topic.length() <= MAX_MAIL_TOPIC_LEN ? topic : topic.substr(0, MAX_MAIL_TOPIC_LEN);
	string strContent = content.length() <= MAX_MAIL_CONTENT_LEN ? content : content.substr(0, MAX_MAIL_CONTENT_LEN);

	GWSendSystemMailReq reqMsg;
	reqMsg.set_destid(destId);
	reqMsg.set_title(strTopic);
	reqMsg.set_content(strContent);
	reqMsg.set_gold(gold);
	reqMsg.set_bindgold(bindGold);
	reqMsg.set_diamond(diamond);
	reqMsg.set_binddiamond(bindDiamond);
	reqMsg.set_arenascore(arenaScore);
	//物品列表的物品统一带到中心服去生成物品，因为发送的目标玩家不一定在当前逻辑服，如果不再当前逻辑服，就取不到目标玩家生成物品的条件数据
	//所以这里统一到中心服再去生成
	LIST_ITEM::iterator iter = lstItem.begin();
	for (; iter != lstItem.end(); ++iter)
	{
		SItem &item = (*iter);
		MailItemProto *proto = reqMsg.add_itemlst();
		if (nullptr != proto)
		{
			proto->set_itemid(item.nItemID);
			proto->set_num(item.nNum);
			proto->set_bind(item.byBind);
		}
	}

	if (!g_GetLogicService()->SendDataToCenter(EMODULE_ID_MAIL, CENTER_SERVER_PROTOCOL_SEND_SYSTEM_MAIL, &reqMsg))
	{
		LogErrFmtPrint("[logic] SendSystemMail...SendDataToCenter failed...destid:%lu,gold:%u,bindGold:%u, diamond:%u, bindDiamond:%u ,arenaScore:%u, topic:%s,content:%s ", destId, gold, bindGold, diamond, bindDiamond, arenaScore, topic.c_str(), content.c_str());
		return false;
	}
	return true;
}
